import cPickle as pickle
import igraph
import logging
import os
import sys


### CONFIGURATION ###
cache_code='1' # 1 for rels+dimes, 2 for rels only.
symmetry = 'order' # double for double listing, order for forced order
methods = ['degree','betweenness','closeness','shell_index','evcent','constraint','pagerank']
arrf_file='data/direction_inference_%s.arff'%symmetry

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s\t%(levelname)s\t%(message)s')
### END OF CONFIGURATION ###

def copy_props(undirected,directed):
    '''
    Copies all the vertice metrics from the undirected graph to the directed one.
    '''
    nodes_props={}
    for v in undirected.vs:
        nodes_props[v['name']]=v.attributes()

    for v in directed.vs:
        if not v['name'] in nodes_props:
            raise ValueError("Node %s is in the directed graph only"%v['name'])
        props=nodes_props[v['name']]
        for prop,val in props.iteritems(): v[prop]=val

def write_arrf(fp,directed,symmetry,methods):
    def node_data(v,methods):
        asn = v['name']
        valstring = ','.join(['%f' % (v[method]) for method in methods])
        return ','.join((asn,valstring))

    def is_p2p(edge, graph):
        return graph.is_mutual(edge.index)

    def should_flip(edge,graph): #This is the ASN version of the func
        source_asn=graph.vs[edge.source]['name']
        dest_asn=graph.vs[edge.target]['name']
        return long(source_asn)>long(dest_asn)
    
    f=file(fp,'w')
    f.write('@relation AS_Link_Inference_%s\n\n' % (symmetry))

    for side in ('left','right'):
        f.write('@attribute %s_asn numeric\n'%side)
        for method in methods:
            f.write('@attribute %s_%s numeric\n' % (side,method))

    f.write('@attribute rel_type {c2p,p2c,p2p}\n\n')
    f.write('@data\n\n')

    for edge in directed.es:
        left_data=node_data(directed.vs[edge.source],methods)
        right_data=node_data(directed.vs[edge.target],methods)
        edge_type='p2c'
        if is_p2p(edge,directed): edge_type='p2p'
        
        if symmetry=='double':
            f.write('%s\n'%','.join((left_data,right_data,edge_type)))
            if edge_type=='p2c':
                edge_type='c2p'
            f.write('%s\n'%','.join((right_data,left_data,edge_type)))

        elif symmetry=='order':
            if should_flip(edge,directed):
                if edge_type=='p2c':
                    edge_type='c2p'
                f.write('%s\n'%','.join((right_data,left_data,edge_type)))
            else:
                f.write('%s\n'%','.join((left_data,right_data,edge_type)))
                

    f.close()
        
def main(): 
    with open('cache/directed.centrality.%s.pkl' % (cache_code), 'rb') as fpkl:
        logging.info('Loading cached version of directed graph with centrality measures')
        directed_graph = pickle.load(fpkl)

    with open('cache/undirected.centrality.%s.pkl' % (cache_code), 'rb') as fpkl:
        logging.info('Loading cached version of undirected graph with centrality measures')
        undirected_graph = pickle.load(fpkl)

    logging.info('Copying the centrality measures from the undirected graph to the directed.')
    copy_props(undirected_graph,directed_graph)

    logging.info('Writing the Arff file.')
    write_arrf(arrf_file,directed_graph,symmetry,methods)

    logging.info('Finished.')

#### MAIN ####
if __name__=='__main__':
    main()
